/**
 * created by dt at 2025/5/6
 */

import { Component } from '../../core/Component';
import { ecs_component } from '../../core/Component';

// 属性修饰器接口
export enum ModifierType {
    Flat = 0,           // 绝对值
    Percentage = 1,     // 百分比（万分比）
    Based = 2,          // 基于其他属性的百分比
} 

// export enum ModifierPriority {
//     Base = 0,           // 基础属性加成
//     Equipment = 1,      // 装备加成
//     Buff = 2,           // 状态效果加成
//     Special = 3,        // 特殊效果加成
// }

// 行为掩码定义
export enum BehaviorMask {
    None = 0,           // 无限制
    CanMove = 1 << 0,   // 可以移动
    CanCastSkill = 1 << 1,  // 可以释放技能
    CanAttack = 1 << 2,     // 可以攻击
    CanBeAttacked = 1 << 3, // 可以被攻击
    CanUseItem = 1 << 4,    // 可以使用道具
    CanInteract = 1 << 5,   // 可以与物体交互
    CanJump = 1 << 6,       // 可以跳跃
    CanSprint = 1 << 7,     // 可以冲刺
    CanDodge = 1 << 8,      // 可以闪避
    CanBlock = 1 << 9,      // 可以格挡
    CanRevive = 1 << 10,    // 可以复活
    CanBeRevived = 1 << 11, // 可以被复活
    CanTrade = 1 << 12,     // 可以交易
    CanChat = 1 << 13,      // 可以聊天
    CanJoinParty = 1 << 14, // 可以加入队伍
    CanJoinGuild = 1 << 15, // 可以加入公会
    All = 0xFFFFFFFF        // 所有行为都允许
}

export class AttributeModifier {
    // 定义万分比转换常量
    public static readonly PERCENTAGE_SCALE = 10000; // 万分比基数

    constructor(
        public readonly type: ModifierType,
        public readonly value: number, // 对于百分比类型，value直接存储万分比整数值
        public readonly priority: number,
        public readonly basedOnAttribute?: number
    ) {}

    // public apply(baseValue: number, basedOnValue?: number): number {
    //     switch (this.type) {
    //         case ModifierType.Flat:
    //             return baseValue + this.value;
    //         case ModifierType.Percentage:
    //             // value已经是万分比整数值，直接使用
    //             return baseValue * (1 + this.value / AttributeModifier.PERCENTAGE_SCALE);
    //         case ModifierType.Based:
    //             if (basedOnValue === undefined) {
    //                 return baseValue;
    //             }
    //             return baseValue + (basedOnValue * this.value / AttributeModifier.PERCENTAGE_SCALE);
    //         default:
    //             return baseValue;
    //     }
    // }

    // 工具方法：将百分比转换为万分比整数值
    public static toPercentageValue(percentage: number): number {
        return Math.round(percentage * AttributeModifier.PERCENTAGE_SCALE);
    }

    // 工具方法：将万分比整数值转换为百分比
    public static fromPercentageValue(value: number): number {
        return value / AttributeModifier.PERCENTAGE_SCALE;
    }
} 
// 基础属性组件
@ecs_component("ECAttribute")
export class ECAttribute extends Component {
    baseValues = new Map<number, number>();
    currentValues = new Map<number, number>();
    dependencies = new Map<number, Set<number>>();
    dirtyFlags = new Set<number>();
    private behaviorMask: number = BehaviorMask.All;  // 默认允许所有行为

    // number(属性id)->{number(priority)->modifier}
    modifiers = new Map<number, Map<number, AttributeModifier[]>>();

    public setBaseValue(type: number, value: number): void {
        this.baseValues.set(type, value);
        this.markDirty(type);
    }

    public getBaseValue(type: number): number {
        return this.baseValues.get(type) || 0;
    }

    public getCurrentValue(type: number): number {
        if (this.dirtyFlags.has(type)) {
            this.recalculateValue(type);
        }
        return this.currentValues.get(type) || 0;
    }

    public setCurrentValue(type: number, value: number): void {
        this.currentValues.set(type, value);
        this.markDirty(type);
    }

    public markDirty(type: number): void {
        // 不重复标记
        if (this.dirtyFlags.has(type)) return;
        this.dirtyFlags.add(type);
        // 标记依赖此属性的其他属性也为脏
        const deps = this.dependencies.get(type);
        if (deps) {
            deps.forEach(dep => this.markDirty(dep));
        }
    }

    private recalculateValue(type: number): void {
        const baseValue = this.getBaseValue(type);
        let finalValue = baseValue;
        
        // 按优先级顺序处理修饰器
        const typeModifiers = this.modifiers.get(type);
        if (typeModifiers) {
            for (const [priority, modifiers] of typeModifiers) {
                if (!modifiers || modifiers.length === 0) continue;

                let totalFlat = 0;
                let totalPercentage = 0;

                // 收集当前优先级的所有修饰器效果
                for (const modifier of modifiers) {
                    if (modifier.type === ModifierType.Flat) {
                        totalFlat += modifier.value;
                    } else if (modifier.type === ModifierType.Percentage) {
                        // value已经是万分比整数值，直接累加
                        totalPercentage += modifier.value;
                    } else if (modifier.type === ModifierType.Based && modifier.basedOnAttribute) {
                        const basedOnValue = this.getCurrentValue(modifier.basedOnAttribute);
                        // 将万分比转换为实际百分比后再计算，并确保整数结果
                        totalFlat += Math.round(basedOnValue * (modifier.value / AttributeModifier.PERCENTAGE_SCALE));
                    }
                }

                // 应用当前优先级的效果，将万分比转换为实际倍率
                // 先计算百分比加成，确保整数结果
                const percentageMultiplier = Math.round((1 + totalPercentage / AttributeModifier.PERCENTAGE_SCALE) * AttributeModifier.PERCENTAGE_SCALE);
                // 应用加成并确保最终结果为整数
                finalValue = Math.round((finalValue + totalFlat) * percentageMultiplier / AttributeModifier.PERCENTAGE_SCALE);
            }
        }

        this.currentValues.set(type, finalValue);
        this.dirtyFlags.delete(type);
    }

    public addModifier(type: number, modifier: AttributeModifier): void {
        if (!this.modifiers.has(type)) {
            this.modifiers.set(type, new Map());
        }
        const typeModifiers = this.modifiers.get(type)!;
        if (!typeModifiers.has(modifier.priority)) {
            typeModifiers.set(modifier.priority, []);
        }
        typeModifiers.get(modifier.priority)!.push(modifier);
        this.markDirty(type);
    }

    public removeModifier(type: number, modifier: AttributeModifier): void {
        const typeModifiers = this.modifiers.get(type);
        if (typeModifiers) {
            const priorityModifiers = typeModifiers.get(modifier.priority);
            if (priorityModifiers) {
                const index = priorityModifiers.indexOf(modifier);
                if (index !== -1) {
                    priorityModifiers.splice(index, 1);
                    if (priorityModifiers.length === 0) {
                        typeModifiers.delete(modifier.priority);
                    }
                    if (typeModifiers.size === 0) {
                        this.modifiers.delete(type);
                    }
                    this.markDirty(type);
                }
            }
        }
    }

    public getModifiers(type: number): AttributeModifier[] {
        const typeModifiers = this.modifiers.get(type);
        if (!typeModifiers) return [];
        
        const allModifiers: AttributeModifier[] = [];
        for (const [_, modifiers] of typeModifiers) {
            if (modifiers) {
                allModifiers.push(...modifiers);
            }
        }
        return allModifiers;
    }

    public getModifiersByPriority(type: number, priority: number): AttributeModifier[] {
        return this.modifiers.get(type)?.get(priority) || [];
    }

    public addDependency(source: number, target: number): void {
        if (!this.dependencies.has(source)) {
            this.dependencies.set(source, new Set());
        }
        this.dependencies.get(source)!.add(target);
    }

    public removeDependency(source: number, target: number): void {                                                                                                                                        
        if (this.dependencies.has(source)) {
            this.dependencies.get(source)!.delete(target);
            if (this.dependencies.get(source)!.size === 0) {
                this.dependencies.delete(source);
            }
        }
    }

    public getDependencies(source: number): Set<number>|undefined {
        return this.dependencies.get(source);
    }

    public hasDependency(source: number, target: number): boolean {
        return this.dependencies.get(source)?.has(target) || false;
    }

    // 行为掩码相关方法
    public setBehaviorMask(mask: number): void {
        this.behaviorMask = mask;
    }

    public addBehaviorMask(mask: number): void {
        this.behaviorMask |= mask;
    }

    public removeBehaviorMask(mask: number): void {
        this.behaviorMask &= ~mask;
    }

    public hasBehaviorMask(mask: number): boolean {
        return (this.behaviorMask & mask) === mask;
    }

    public getBehaviorMask(): number {
        return this.behaviorMask;
    }

    // 检查是否可以执行某个行为
    public canPerformBehavior(behavior: BehaviorMask): boolean {
        return this.hasBehaviorMask(behavior);
    }

    // 检查是否可以执行多个行为
    public canPerformBehaviors(behaviors: BehaviorMask): boolean {
        return this.hasBehaviorMask(behaviors);
    }

    onRecycle(): void {
        this.baseValues.clear();
        this.currentValues.clear();
        this.dependencies.clear();
        this.dirtyFlags.clear();
        this.modifiers.clear();
        this.behaviorMask = BehaviorMask.All;
    }

    onReuse(): void {
        // 重置所有属性到初始状态
        this.baseValues.clear();
        this.currentValues.clear();
        this.dependencies.clear();
        this.dirtyFlags.clear();
        this.modifiers.clear();
        this.behaviorMask = BehaviorMask.All;
    }
}
